package com.smh.demo1.a39;

import org.springframework.aop.framework.Advised;
import org.springframework.context.annotation.AnnotationConfigUtils;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.support.GenericApplicationContext;

import java.lang.reflect.Method;

/**
 * @author shiminghui
 * @date 2025/5/9 20:52
 * @description: TODO
 */
public class A39 {
    public static void main(String[] args) throws Exception {

        GenericApplicationContext context = new GenericApplicationContext();
        // 注册一些常用的BeanFactory和Bean后处理器
        AnnotationConfigUtils.registerAnnotationConfigProcessors(context);

        context.registerBean(MyConfig.class);
        context.refresh();
        // 打印
        String[] beanDefinitionNames = context.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }

        // 可以看到 代理对象 并没有代理Bean1 的init方法和afterPropertiesSet方法
        // 因为代理对象的创建是在Bean1初始化完成之后创建的,而Bean1的init方法和afterPropertiesSet方法在Bean1初始化之前执行,所以代理对象无法代理到这些方法上
        // 但是后面调用时可以
        Bean1 bean = context.getBean(Bean1.class);
//        bean.init();

        // 测试代理对象的属性是否有值
        // 发现没有值,为什么？ 因为代理对象是是在Bean1初始化后创建的,spring没有为代理对象注入属性
        showAttribute(bean);

        System.out.println("------------------");

        // 测试代理对象的方法是否被代理
        bean.m1();
        bean.m2();
        bean.m3();
        Method m4 = Bean1.class.getDeclaredMethod("m4");
        m4.setAccessible(true);
        m4.invoke(bean);
        // 发现只有m1方法被代理,其他方法没有被代理
        // 注: 只有可以重写的方法才会被代理 static final private 修饰的方法都无法代理

    }

    private static void showAttribute(Bean1 proxy) throws Exception {
        System.out.println("代理对象的属性");
        System.out.println(proxy.flag);
        System.out.println(proxy.initialValue);
        System.out.println("------------------");
        System.out.println("原始对象的属性");
        if (proxy instanceof Advised advised) {
            Bean1 target = (Bean1) advised.getTargetSource().getTarget();
            System.out.println(target.flag);
            System.out.println(target.initialValue);
        }
    }

    @Configuration
    @ComponentScan
    @EnableAspectJAutoProxy // 开启AOP功能
    static class MyConfig {

    }
}
